package com.google.code.UtopiaXml;

import java.util.Objects;

/**
 * Class representing simpleTypes that are mapped to Java object types
 *
 * @author Michael Simacek
 */
public class SimpleTypeReference implements SimpleType {

    private String typeName;
    private String importName;
    private String loader;
    private String defaultValue;

    /**
     * Creates SimpleTypeReference with given type name and loader method
     *
     * @param typeName fully-qualified name of the type
     * @param loaderMethod loader method name that will be placed in and
     * assignment followed by brackets with String variable. It should be able
     * to parse String into given type. It can also be a constructor call (for
     * example "new BigDecimal")
     */
    public SimpleTypeReference(String typeName, String loaderMethod) {
        this.importName = CodeBuilder.getImportFromFullName(typeName);
        this.typeName = CodeBuilder.getNameFromFullName(typeName);
        this.loader = loaderMethod;
    }

    /**
     * Creates SimpleTypeReference with given type name and default loader
     * method (typename.valueOf)
     *
     * @param typeName fully-qualified name of the type
     */
    public SimpleTypeReference(String typeName) {
        this(typeName, CodeBuilder.getNameFromFullName(typeName) + ".valueOf");
    }

    @Override
    public String getImport() {
        return importName;
    }

    @Override
    public String getDefaultValue() {
        return defaultValue;
    }

    /**
     * Sets a default value of the type that will be used as a rvalue in an
     * initialization.
     *
     * @param defaultValue
     */
    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    @Override
    public void appendLoaderFromElement(CodeBuilder cb, String nodeName, String resName) {
        cb.appendLine("//begin SimpleTypeReference");
        cb.appendLine(typeName + " " + resName + " = " + defaultValue + ";");
        cb.appendLine("if (" + nodeName + ".getFirstChild() != null) {");
        cb.appendLine(resName + " = " + loader + "("
                      + nodeName + ".getFirstChild().getNodeValue());");
        cb.appendLine("}");
        cb.addImport(importName);
        cb.appendLine("//end SimpleTypeReference");
    }

    @Override
    public void appendLoaderFromString(CodeBuilder cb, String string, String resName) {
        cb.appendLine("//begin SimpleTypeReference");
        cb.appendLine(typeName + " " + resName + " = " + loader + "("
                      + string + ");");
        cb.addImport(importName);
        cb.appendLine("//end SimpleTypeReference");
    }

    @Override
    public String getTypeName() {
        return typeName;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + Objects.hashCode(this.typeName);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SimpleTypeReference other = (SimpleTypeReference) obj;
        if (!Objects.equals(this.typeName, other.typeName)) {
            return false;
        }
        return true;
    }

    @Override
    public SimpleType copy() {
        SimpleTypeReference ret = new SimpleTypeReference(typeName, loader);
        ret.setDefaultValue(defaultValue);
        return ret;
    }
}
